#include "UamMsgProcess.h"
#include <qbkernel/include/qb_base.h>
#include <qbprotocol/include/rdProto.h>
#include <qbprotocol/include/SSQBModel.h>
#include <qbprotocol/include/MessageParserTool.h>
#include <core/Utility.h>

#ifdef _MSC_VER
#pragma comment(lib, "ws2_32.lib")
#endif

using namespace qb;
#define Reg_Func(ID) qb::qbBase::getMessageBond()->RegisterDecodeFunc(ID, uam::ExtracFunc)
#define DelPtr(FUNC, TYPE) \
	case FUNC:\
	{\
		TYPE* p = static_cast<TYPE*>(toDel);\
		delete p;\
		return nullptr;\
	}\
	break;
	

namespace uam
{
	void* delAck(int func, void* toDel)
	{
		switch (func)
		{
			DelPtr(E_FID_QB_ALL_CMPY_QRY, xQBTradeCmpyInfoListAck_c);
			DelPtr(E_FID_QB_FLAGS_REQ, xQBFlagsAck_c);
			DelPtr(E_FID_QB_GLOBAL_SWITCH, xQBGlobalSwitchAck_t);
			DelPtr(E_FID_QB_QUERY_NEW_UERINFO_REQ, QBAccountInfoNewAck_t);
			DelPtr(E_FID_QB_USEPROTOCAL_QUERY_REQ, QBUseProtocolQueryAck);
			DelPtr(E_FID_QB_USER_MEMBER_INFO_REQ, xUserMemberInfoAck_c);
			DelPtr(E_FID_QB_AUTHORITY_QUERY_NEW_REQ, xQBAuthorityQueryAck_c);
		default:
			break;
		}
		return toDel;
	}
	void* ExtracFunc(int func, const ProtoMessage& msg, void* toDel)
	{
		if (toDel != nullptr)
			return delAck(func, toDel);

		void* data = nullptr;
		switch (func)
		{
		case E_FID_QB_ALL_CMPY_QRY:
		{
			ProtoList msglist;
			if (!msg.getList("List", msglist))
				return nullptr;

			xQBTradeCmpyInfoListAck_c* ptr = new xQBTradeCmpyInfoListAck_c();
			data = ptr;
			xQBTradeCmpyInfo_c	tradeinfo_unit;

			for (ProtoList::const_iterator it = msglist.begin(); it != msglist.end(); ++it)
			{
				if (it->Type != ProtoValue::VAR_MAP)
					continue;

				memset(&tradeinfo_unit, 0, sizeof(xQBTradeCmpyInfo_c));
				const ProtoMap& msgmap = *it;

				bool bret = msgmap.GetInt32("Id", tradeinfo_unit.m_Id);
				if (!bret) continue;//以防错误的数据
				FIELDCOPY(tradeinfo_unit.m_Name, CParserTool::GetString(msgmap, "Name"));
				FIELDCOPY(tradeinfo_unit.m_Code, CParserTool::GetString(msgmap, "Code"));
				FIELDCOPY(tradeinfo_unit.m_EnName, CParserTool::GetString(msgmap, "EnName"));
				FIELDCOPY(tradeinfo_unit.m_FullName, CParserTool::GetString(msgmap, "FullName"));

				FIELDCOPY(tradeinfo_unit.m_Address, CParserTool::GetString(msgmap, "Address"));
				FIELDCOPY(tradeinfo_unit.m_PostCode, CParserTool::GetString(msgmap, "PostCode"));
				FIELDCOPY(tradeinfo_unit.m_Tel, CParserTool::GetString(msgmap, "Tel"));
				FIELDCOPY(tradeinfo_unit.m_Fax, CParserTool::GetString(msgmap, "Fax"));
				FIELDCOPY(tradeinfo_unit.m_Email, CParserTool::GetString(msgmap, "Email"));

				ptr->m_List.push_back(tradeinfo_unit);
			}

			xQBTradeCmpContact_c contact_unit;
			if (msg.GetList("ContactList", msglist))
			{
				for (ProtoList::const_iterator it = msglist.begin();
					it != msglist.end(); ++it)
				{
					if (it->Type != ProtoValue::VAR_MAP)
						continue;

					memset(&contact_unit, 0, sizeof(xQBTradeCmpContact_c));
					const ProtoMap& msgmap = *it;

					msgmap.GetInt32("ID", contact_unit.m_ID);
					msgmap.GetInt32("CompanyId", contact_unit.m_CompanyId);
					FIELDCOPY(contact_unit.m_Contact, CParserTool::GetString(msgmap, "Contact"));
					FIELDCOPY(contact_unit.m_EName, CParserTool::GetString(msgmap, "EName"));
					FIELDCOPY(contact_unit.m_TEL, CParserTool::GetString(msgmap, "TEL"));
					FIELDCOPY(contact_unit.m_Dept, CParserTool::GetString(msgmap, "Dept"));
					FIELDCOPY(contact_unit.m_QM, CParserTool::GetString(msgmap, "QM"));
					FIELDCOPY(contact_unit.m_QQ, CParserTool::GetString(msgmap, "QQ"));
					FIELDCOPY(contact_unit.m_MSN, CParserTool::GetString(msgmap, "MSN"));
					FIELDCOPY(contact_unit.m_RM, CParserTool::GetString(msgmap, "RM"));
					FIELDCOPY(contact_unit.m_QQEnterprise, CParserTool::GetString(msgmap, "QQEnterprise"));

					ptr->m_ContactList.push_back(contact_unit);

				}
			}

			msg.GetInt32("SaveType", ptr->m_SaveType);
		}
		break;
		case E_FID_QB_FLAGS_REQ:
		{
			xQBFlagsAck_c* pFlags = new xQBFlagsAck_c();
			data = pFlags;

			FIELDCOPY(pFlags->m_CompanyID, CParserTool::GetString(msg, "CompanyID"));
			FIELDCOPY(pFlags->m_UserId, CParserTool::GetString(msg, "UserID"));

			ProtoList sublist;
			if (!msg.GetList("List", sublist)) return nullptr;
			for (ProtoList::const_iterator it = sublist.begin(); it != sublist.end(); ++it)
			{
				const ProtoMap& msgmap = *it;
				char szKey[64] = { 0 }; char szVal[1024] = { 0 };
				FIELDCOPY(szKey, CParserTool::GetString(msgmap, "Key"));
				FIELDCOPY(szVal, CParserTool::GetString(msgmap, "Value"));

				pFlags->listFlags.push_back(xQbFlag_c(szKey, szVal));
			}
		}
		break;
		case E_FID_QB_GLOBAL_SWITCH:
		{
			xQBGlobalSwitchAck_t* ptr = new xQBGlobalSwitchAck_t();
			data = ptr;
			FIELDCOPY(ptr->m_Version, CParserTool::GetString(msg, "Version"));
			FIELDCOPY(ptr->m_UserID, CParserTool::GetString(msg, "UserID"));

			ProtoList msglist;
			if (!msg.getList("Flags", msglist))
			{
				delete ptr;
				return nullptr;
			}

			char skey[64] = { 0 };
			char svalue[512] = { 0 };
			for (ProtoList::const_iterator it = msglist.begin(); it != msglist.end(); ++it) {
				if (it->Type != ProtoValue::VAR_MAP)
					continue;
				const ProtoMap& msgmap = *it;
				memset(skey, 0, sizeof(skey));
				memset(svalue, 0, sizeof(svalue));
				FIELDCOPY(skey, CParserTool::GetString(msgmap, "Key"));
				FIELDCOPY(svalue, CParserTool::GetString(msgmap, "Value"));

				if (strlen(skey) > 0 && strlen(svalue) > 0) {
					ptr->m_Flags[skey] = svalue;
					log_debug("GlobalVarible [%s] = (%s)", skey, svalue);
				}
			}

		}
		break;
		case E_FID_QB_QUERY_NEW_UERINFO_REQ:
		{
			QBAccountInfoNewAck_t* ptr = new QBAccountInfoNewAck_t();
			data = ptr;
			FIELDCOPY(ptr->m_UserId, CParserTool::GetString(msg, "UserId"));
			FIELDCOPY(ptr->m_Password, CParserTool::GetString(msg, "Password"));
			FIELDCOPY(ptr->m_UserName, CParserTool::GetString(msg, "UserName"));
			FIELDCOPY(ptr->m_DisplayName, CParserTool::GetString(msg, "DisplayName"));
			const char* str = 0;
			size_t len = 0;
			if (msg.RefString("DisplayName", str, len) && str && len > 0)
			{
				if (len > _countof(ptr->m_DisplayName_Utf8)) len = _countof(ptr->m_DisplayName_Utf8) - 1;
				#ifdef _MSC_VER
				strncpy_s(ptr->m_DisplayName_Utf8, _countof(ptr->m_DisplayName_Utf8), str ? str : "", len);
				#else
				strncpy(ptr->m_DisplayName_Utf8, str ? str : "", len);
				#endif
			}
			FIELDCOPY(ptr->m_CompanyId, CParserTool::GetString(msg, "CompanyId"));
			FIELDCOPY(ptr->m_CompanyName, CParserTool::GetString(msg, "CompanyName"));
			FIELDCOPY(ptr->m_AccountType, CParserTool::GetString(msg, "AccountType"));
			FIELDCOPY(ptr->m_ExpireDate, CParserTool::GetString(msg, "ExpireDate"));
			FIELDCOPY(ptr->m_Telephone, CParserTool::GetString(msg, "Telephone"));
			FIELDCOPY(ptr->m_Mobile, CParserTool::GetString(msg, "Mobile"));
			FIELDCOPY(ptr->m_Rm, CParserTool::GetString(msg, "Rm"));
			FIELDCOPY(ptr->m_Msn, CParserTool::GetString(msg, "Msn"));
			FIELDCOPY(ptr->m_QQ, CParserTool::GetString(msg, "QQ"));
			FIELDCOPY(ptr->m_Address, CParserTool::GetString(msg, "Address"));
			FIELDCOPY(ptr->m_Department, CParserTool::GetString(msg, "Department"));
			FIELDCOPY(ptr->m_BussinessType, CParserTool::GetString(msg, "BussinessType"));
			FIELDCOPY(ptr->m_Title, CParserTool::GetString(msg, "Title"));
			FIELDCOPY(ptr->m_QQEnterprise, CParserTool::GetString(msg, "QQEnterprise"));
			FIELDCOPY(ptr->m_QQEnterprise_Company, CParserTool::GetString(msg, "QQEnterprise_Company"));
			char* pos = strchr(ptr->m_ExpireDate, ' ');
			if (pos)
				ptr->m_ExpireDate[pos - ptr->m_ExpireDate] = '\0';

			ProtoList msglist;
			if (msg.getList("lstPhone", msglist)) {
				ProtoMap submsg;
				for (ProtoList::const_iterator it = msglist.begin(); it != msglist.end(); ++it) {
					if (it->Type != ProtoValue::VAR_MAP) continue;
					const ProtoMap& msgmap = *it;
					xQBAccountInfoNewAckUnit unit;
					FIELDCOPY(unit.m_Type, CParserTool::GetString(msgmap, "Type"));
					FIELDCOPY(unit.m_Phone, CParserTool::GetString(msgmap, "Phone"));
					ptr->m_lstPhone.push_back(unit);
				}
			}
		}
		break;
		case E_FID_QB_USEPROTOCAL_QUERY_REQ:
		{
			QBUseProtocolQueryAck* ptr = new QBUseProtocolQueryAck();
			data = ptr;
			FIELDCOPY(ptr->m_UserId, CParserTool::GetString(msg, "UserId"));
			FIELDCOPY(ptr->m_UserAccount, CParserTool::GetString(msg, "UserAccount"));
			FIELDCOPY(ptr->m_UserName, CParserTool::GetString(msg, "UserName"));
			FIELDCOPY(ptr->m_InstitutionID, CParserTool::GetString(msg, "InstitutionID"));
			FIELDCOPY(ptr->m_InstitutionName, CParserTool::GetString(msg, "InstitutionName"));
		}
		break;
		case E_FID_QB_USER_MEMBER_INFO_REQ:
		{
			xUserMemberInfoAck_c* userMemberInfo = new xUserMemberInfoAck_c();
			data = userMemberInfo;
			FIELDCOPY(userMemberInfo->m_UserId, CParserTool::GetString(msg, "UserId"));
			FIELDCOPY(userMemberInfo->m_UserAccount, CParserTool::GetString(msg, "UserAccount"));
			FIELDCOPY(userMemberInfo->m_CompanyId, CParserTool::GetString(msg, "CompanyId"));
			FIELDCOPY(userMemberInfo->m_MemberLevel, CParserTool::GetString(msg, "MemberLevel"));
			FIELDCOPY(userMemberInfo->m_IsPaidCustom, CParserTool::GetString(msg, "IsPaidCustom"));
			msg.GetInt32("CurrentMonthBp", userMemberInfo->m_CurrentMonthBp);
			msg.GetInt32("TotalBp", userMemberInfo->m_TotalBp);
			msg.GetInt32("OpenPageBpCanGetToday", userMemberInfo->m_OpenPageBpCanGetToday);
			FIELDCOPY(userMemberInfo->m_FirstLogInReceived, CParserTool::GetString(msg, "FirstLogInReceived"));
			FIELDCOPY(userMemberInfo->m_FirstOpenRecommendReceived, CParserTool::GetString(msg, "FirstOpenRecommendReceived"));

			ProtoList sublist;
			if (msg.GetList("ListLevel", sublist))
			{
				for (ProtoList::const_iterator it = sublist.begin(); it != sublist.end(); ++it)
				{
					const ProtoMap& msgmap = *it;
					sUserMemberLevelList levelUnit;
					msgmap.GetInt32("Level", levelUnit.m_Level);
					msgmap.GetInt32("MinBp", levelUnit.m_MinBp);
					userMemberInfo->m_ListLevel.push_back(levelUnit);
				}
			}
		}
		break;
		case E_FID_QB_AUTHORITY_QUERY_NEW_REQ:
		{
			xQBAuthorityQueryAck_c* ptr = new xQBAuthorityQueryAck_c();
			data = ptr;
			FIELDCOPY(ptr->m_UserId, CParserTool::GetString(msg, "UserId"));
			FIELDCOPY(ptr->m_OverSeaFlag, CParserTool::GetString(msg, "OverSeaFlag"));
			msg.getInt32("AllowOpenQM", ptr->m_AllowOpenQM);
			msg.getInt32("AllowAlltab", ptr->m_AllowAlltab);
			msg.getInt32("AllowMarketStream", ptr->m_AllowMarketStream);

			ProtoList msglist;
			if (msg.getList("BusinessList", msglist))
			{
				for (ProtoList::const_iterator it = msglist.begin(); it != msglist.end(); ++it)
				{
					if (it->Type != ProtoValue::VAR_MAP)
						continue;

					const ProtoMap& msgmap = *it;
					xQBAuthorityBusiness_c businessUnit;
					FIELDCOPY(businessUnit.m_BrokerID, CParserTool::GetString(msgmap, "BrokerID"));
					FIELDCOPY(businessUnit.m_BrokerName, CParserTool::GetString(msgmap, "BrokerName"));
					FIELDCOPY(businessUnit.m_CompanyType, CParserTool::GetString(msgmap, "CompanyType"));
					FIELDCOPY(businessUnit.m_AllowName, CParserTool::GetString(msgmap, "AllowName"));
					FIELDCOPY(businessUnit.m_AllowNameEn, CParserTool::GetString(msgmap, "AllowNameEn"));
					FIELDCOPY(businessUnit.m_Abbr, CParserTool::GetString(msgmap, "abbr"));
					FIELDCOPY(businessUnit.m_BusinessAllowId, CParserTool::GetString(msgmap, "BusinessAllowId"));
					FIELDCOPY(businessUnit.m_AllowName, CParserTool::GetString(msgmap, "AllowName"));
					FIELDCOPY(businessUnit.m_AllowNameEn, CParserTool::GetString(msgmap, "AllowNameEn"));
					FIELDCOPY(businessUnit.m_BusinessName, CParserTool::GetString(msgmap, "BusinessName"));
					FIELDCOPY(businessUnit.m_BusinessCode, CParserTool::GetString(msgmap, "BusinessCode"));
					FIELDCOPY(businessUnit.m_BusinessLevel, CParserTool::GetString(msgmap, "BusinessLevel"));
					FIELDCOPY(businessUnit.m_Email, CParserTool::GetString(msgmap, "Email"));
					FIELDCOPY(businessUnit.m_UserName, CParserTool::GetString(msgmap, "UserName"));
					FIELDCOPY(businessUnit.m_ContactName, CParserTool::GetString(msgmap, "ContactName"));
					FIELDCOPY(businessUnit.m_ContactTEL, CParserTool::GetString(msgmap, "ContactTEL"));
					msgmap.getInt32("Status_C", businessUnit.m_Status_C);
					msgmap.getInt32("Status_T", businessUnit.m_Status_T);
					msgmap.getInt32("Status_B", businessUnit.m_Status_B);

					// sub list 
					ProtoList msgsublist;
					if (msgmap.getList("BrokerList", msgsublist))
					{
						for (ProtoList::const_iterator iit = msgsublist.begin(); iit != msgsublist.end(); ++iit)
						{
							if (iit->Type != ProtoValue::VAR_MAP)
								continue;
							const ProtoMap& submsgmap = *iit;
							xQBAuthorityBroker_c BrokerUnit;
							FIELDCOPY(BrokerUnit.m_UserName, CParserTool::GetString(submsgmap, "UserName"));
							FIELDCOPY(BrokerUnit.m_DisplayName, CParserTool::GetString(submsgmap, "DisplayName"));
							FIELDCOPY(BrokerUnit.m_Mobile, CParserTool::GetString(submsgmap, "Mobile"));
							FIELDCOPY(BrokerUnit.m_Department, CParserTool::GetString(submsgmap, "Department"));
							FIELDCOPY(BrokerUnit.m_TEL, CParserTool::GetString(submsgmap, "TEL"));
							FIELDCOPY(BrokerUnit.m_Email, CParserTool::GetString(submsgmap, "Email"));

							businessUnit.m_BrokerList.push_back(BrokerUnit);
						}
					}
					ptr->m_BusinessList.push_back(businessUnit);
				}
			}

			if (msg.getList("ItemList", msglist))
			{
				for (ProtoList::const_iterator it = msglist.begin(); it != msglist.end(); ++it)
				{
					if (it->Type != ProtoValue::VAR_MAP)
						continue;

					const ProtoMap& msgmap = *it;
					xLevelItem_c levelItem;
					FIELDCOPY(levelItem.m_BusinessLevel, CParserTool::GetString(msgmap, "BusinessLevel"));
					FIELDCOPY(levelItem.m_ItemKey, CParserTool::GetString(msgmap, "ItemKey"));
					FIELDCOPY(levelItem.m_Value, CParserTool::GetString(msgmap, "Value"));
					FIELDCOPY(levelItem.m_PriceType, CParserTool::GetString(msgmap, "PriceType"));
					FIELDCOPY(levelItem.m_MemoFlag, CParserTool::GetString(msgmap, "MemoFlag"));

					ptr->m_ItemList.push_back(levelItem);
				}
			}
		}
		break;
		default:
			break;
		}

		return data;
	}

	void InitDecodeFuncs()
	{
		Reg_Func(E_FID_QB_ALL_CMPY_QRY);
		Reg_Func(E_FID_QB_FLAGS_REQ);
		Reg_Func(E_FID_QB_GLOBAL_SWITCH);
		Reg_Func(E_FID_QB_QUERY_NEW_UERINFO_REQ);
		Reg_Func(E_FID_QB_USEPROTOCAL_QUERY_REQ);
		Reg_Func(E_FID_QB_USER_MEMBER_INFO_REQ);
		Reg_Func(E_FID_QB_AUTHORITY_QUERY_NEW_REQ);
	}

}

